/**
 * @fileoverview
 * TODO doc me
 */


// Shortcuts
var log = YAHOO.log;
var assert = YAHOO.util.Assert;


// ************************************************************
// MODULE TESTS
// ************************************************************


/**
 * TODO declare the class
 */
flyui.flyted.GeneNameMappings.Tests = function(){};


/** 
 * Test that the contents of the flyui.flyted.GeneNameMappings module have been defined.
 */
flyui.flyted.GeneNameMappings.Tests.testModuleContents = function() {
	
	log("Test \"==== flyui.flyted.GeneNameMappings Tests :: testModuleContents ====\" started.");
	
	assert.isNotUndefined(flyui.flyted.GeneNameMappings, "flyui.flyted.GeneNameMappings is undefined");	
	
	assert.isNotUndefined(flyui.flyted.GeneNameMappings.flytedToFlybase, "flyui.flyted.GeneNameMappings.flytedToFlybase");
    assert.isNotUndefined(flyui.flyted.GeneNameMappings.flybaseToFlyted, "flyui.flyted.GeneNameMappings.flybaseToFlyted");
	
};


flyui.flyted.GeneNameMappings.Tests.testMissingT2BMappingsAreNotMissing = function() {

    log("Test \"==== flyui.flyted.GeneNameMappings Tests :: testMissingT2BMappingsAreNotMissing ====\" started.");
	
	var expectedT2BMappings = [
		["acer", "FBgn0016122"],
		["TektinA", "FBgn0028902"],
		["mi-2", "FBgn0013591"],
		["Mst-35Ba", "FBgn0013300"],
		["Hex T2", "FBgn0042710"],
		["CG12819/sle", "FBgn0037810"],
		["scpr-b", "FBgn0037888"],
		["prx2540", "FBgn0033520"],
		["Acp63.F", "FBgn0015585"],
		// TODO Helen is unsure about this, needs to look at primer sequence
		// "est-2" 
		["nfx4", "FBgn0051501"],
		["CG10998/r-cup", "FBgn0031142"],
		["aurora b", "FBgn0024227"],
		["CG10723/Kua", "FBgn0032850"],
		["Mfn/Marf", "FBgn0029870"],
		["mst87f", "FBgn0002862"],
		["so-c", "FBgn0003460"],
		["so-n", "FBgn0003460"],
		["CG32394N", "FBgn0052394"],
		["mat1", "FBgn0024956"],
		["CG4700-sema-2a", "FBgn0011260"],
		["mst35ba", "FBgn0013300"],
		["CG31992-gw", "FBgn0051992"],
		["sapr", "FBgn0000416"],
		["rpn6", "FBgn0028689"],
		["CG7570/hale", "FBgn0036924"],
		["alh", "FBgn0037471"],
		["su(tpl)", "FBgn0014037"],
		["CG14016/tomb", "FBgn0031715"],
		["Pi3k59F", "FBgn0015277"],
		["Cct-2", "FBgn0035231"],
		["CG17736/schuy", "FBgn0036925"],
		["d-cup", "FBgn0038089"],
		// ["prosalpha1", "FBgn0026781 AND FBgn0050382"], // N.B. Helen says there is a gene duplication event, so genes are identical
        ["prosalpha1", "FBgn0026781"],
        ["prosalpha1", "FBgn0050382"],
		["Nrx4", "FBgn0013997"],
		["tfb1", "FBgn0033929"],
		["SlgA", "FBgn0003423"],
		["p-cup", "FBgn0030840"],
		["CR32886-Uhg1", "FBgn0045800"],
		["swapsi", "FBgn0016974"],
		["Rno", "FBgn0035106"],
		["CG10034/tj", "FBgn0000964"],
		["cirl", "FBgn0033313"],
		["des/ifc", "FBgn0001941"],
		["Pros28.1b", "FBgn0017556"] 
	];

    var assertT2BMappingIsPresent = function(t, b) {
        log("assert mapping found from flyted name: "+t+" to flybase name: "+b, "test");
        var t2b = flyui.flyted.GeneNameMappings.flytedToFlybase;
        var bs = t2b[t];
        assert.isNotUndefined(bs, "no mappings found for flyted name: "+t);
        assert.isTrue(flyui.util.isArrayMember(bs, b), "expected flyted name "+t+" maps to flybase name "+b+", found "+bs.join(", "));
    } 	

    for (var i=0; i<expectedT2BMappings.length; i++) {
        var mapping = expectedT2BMappings[i];
        var t = mapping[0];
        var b = mapping[1];
        assertT2BMappingIsPresent(t,b);
    }

};


flyui.flyted.GeneNameMappings.Tests.testAmbiguousT2BMappingsAreFixed = function() {

    log("Test \"==== flyui.flyted.GeneNameMappings Tests :: testAmbiguousT2BMappingsAreFixed ====\" started.");
	
	var expectedUnambiguousT2BMappings = [
		["smooth", "FBgn0003435"],
		["B52", "FBgn0004587"],
		["fdl", "FBgn0045063"],
		["rbf", "FBgn0015799"],
		["bam", "FBgn0000158"],
		["l(1)G0255", "FBgn0028336"],
		["pip", "FBgn0003089"],
		["sip2", "FBgn0031878"],
		["Srp54", "FBgn0024285"],
		["And", "FBgn0011273"],
		["CG11765", "FBgn0033518"],
		["sdt", "FBgn0243505"],
		["l(2)02045", "FBgn0010504"],
		["Cam", "FBgn0000253"],
		["CG10022", "FBgn0051960"],
		["twe", "FBgn0002673"],
		["sd", "FBgn0003345"],
		["dsh", "FBgn0000499"],
		["swa", "FBgn0003655"],
		["spin", "FBgn0086676"],
		// "* mle -> FBal0012332 FBgn0002774","FBgn0002715","maleless", 
		// assume Helen's error, mle is FBgn0002774 (maleless)
		["mle", "FBgn0002774"],
		// "* mei-S332 -> FBal0012188 FBgn0002715  "
		// assume Helen's error, mei-S332 is FBgn0002715 (meiotic from via Salaria 332)
		["mei-S332", "FBgn0002715"]		
	];
	
	var assertT2BMappingIsUnambiguous = function(t, b) {
        log("assert unambiguous mapping from flyted name: "+t+", expect flybase name: "+b, "test");
        
        var t2b = flyui.flyted.GeneNameMappings.flytedToFlybase;
        
        // check mapping from flyted to flybase
        assert.isNotUndefined(t2b[t], "no mapping found for flyted name: "+t);
        assert.areEqual(1, t2b[t].length, "expected 1 flybase name for flyted name "+t+", found "+t2b[t].length);
        assert.areEqual(b, t2b[t][0], "expected flyted name "+t+" maps to flybase name "+b+", found "+t2b[t].join(", "));

	};
	
	for (var i=0; i<expectedUnambiguousT2BMappings.length; i++) {
		var mapping = expectedUnambiguousT2BMappings[i];
		var t = mapping[0];
		var b = mapping[1];
		assertT2BMappingIsUnambiguous(t,b);
	}

};


flyui.flyted.GeneNameMappings.Tests.testB2TMappings = function() {
    log("Test \"==== flyui.flyted.GeneNameMappings Tests :: testB2TMappings ====\" started.");
	
	var expectedB2TMappings = [

// Helen: "* FBgn0052548 -> CG32548 CG6306","both primer pairs amplify transcript CG32548-RC (FBtr0074569) but not CG32548-RB",
// FBgn0052548 is CG32548 according to flybase
// CG6306 is listed as a synonym for FBgn0052548
// looking at gene model and products, see multiple transcripts
// because both primer pairs amplify one of the gene's transcripts, and because 
// CG6306 is listed as a synonym, suggest to keep as a promiscuous mapping...

        ["FBgn0052548", ["CG32548", "CG6306"]],
    
// Helen: "* FBgn0010747 -> Srp54k Srp54","Srp54 and Srp54k are different genes. we have done both.",
// According to flybase, FBgn0010747 is Srp54k
// Srp54 is FBgn0024285
// because these are different genes, suggest to disambiguate as per flybase...

        ["FBgn0010747", ["Srp54k"]],
        ["FBgn0024285", ["Srp54"]],

// Helen: "* FBgn0042189 -> CG17376 CG18461","CG18461 and CG17376 annotations were merged.  both primer pairs amplify transcript CG17376-RB but not CG17376-RA.",
// According to flybase, FBgn0042189 is CG17376, with CG18461 as a synonym
// because both primer pairs amplify a transcript of FBgn0042189, suggest to keep as promiscuous mapping...

        ["FBgn0042189", ["CG17376", "CG18461"]],

// Helen: "* FBgn0032859 -> Arc-p34 ArcP34","typo",
// keep as promiscuous mapping to work around typo...

        ["FBgn0032859", ["Arc-p34", "ArcP34"]],

// Helen: "* FBgn0037462 -> sunz CG15179","synonyms; sunz (sungrazer) is the new name for CG15179",
// keep promiscuous mapping to work around synonyms...

        ["FBgn0037462", ["sunz", "CG15179"]],

// Helen: "* FBgn0032439 -> ref2 CG17031","synonyms; ref2 is the new name for CG17031",
// keep promiscuous mapping to work around synonyms...

        ["FBgn0032439", ["ref2", "CG17031"]],

// Helen: "* FBgn0052392 -> CG10099 CG32392","cg32392 was formed from a merge of CG10099 and CG14912.  both primer pairs designed to same transcript",
// keep promiscuous mapping, as both primers amplify same transcript

        ["FBgn0052392", ["CG10099", "CG32392"]],

// Helen: "* FBgn0002838 -> ms(3)K81 CG14251","synonyms.",
// keep promiscuous mapping to work around synonyms...

        ["FBgn0002838", ["ms(3)K81", "CG14251"]],

// Helen: "* FBgn0004903 -> Rb97D rbf  ","We have done Rb97D and Rbf.  confusion comes as rbf is listed as a synonym of Rb97D",
// Flybase has FBgn0004903 as Rb97D
// rbf is FBgn0015799
// suggest to disambiguate as per flybase...

        ["FBgn0004903", ["Rb97D"]],
        ["FBgn0015799", ["rbf"]]

	];
	
	var assertB2TMapping = function(b, ets) {
		log("assert flybase name "+b+" maps to flyted names "+ets.join(", "), "test");
		
        var b2t = flyui.flyted.GeneNameMappings.flybaseToFlyted;
		var ats = b2t[b];

        assert.isNotUndefined(ats, "no mappings found for "+b);
        assert.isTrue(flyui.util.arrayMembersAreEqual(ets, ats), "expected: "+ets.join(", ")+", actual: "+ats.join(", "));		
		
	};
	
	for (var i=0; i<expectedB2TMappings.length; i++) {
		var mapping = expectedB2TMappings[i];
		var b = mapping[0];
		var ts = mapping[1];
		assertB2TMapping(b,ts);
	}
};


flyui.flyted.GeneNameMappings.Tests.testReverseOfNewT2BMappings = function() {
    log("Test \"==== flyui.flyted.GeneNameMappings Tests :: testReverseOfNewT2BMappings ====\" started.");

    var expectedB2TMappings = [    
    
        ["FBgn0016122", ["acer"]],
        ["FBgn0028902", ["TektinA"]],
        ["FBgn0013591", ["mi-2"]],
        
        // assumed typo variant mst35ba
        ["FBgn0013300", ["Mst-35Ba", "mst35ba"]],
        
        // added assumed typo variant Hex-t2
        ["FBgn0042710", ["Hex T2", "Hex-t2"]],
        
        ["FBgn0037810", ["CG12819/sle"]],
        ["FBgn0037888", ["scpr-b"]],
        ["FBgn0033520", ["prx2540"]],
        ["FBgn0015585", ["Acp63.F"]],
        
        // TODO Helen is unsure about this, needs to look at primer sequence
        // ["???", ["est-2"]] 

        ["FBgn0051501", ["nfx4"]],
        
        // added assumed typo variant CG10998
        ["FBgn0031142", ["CG10998/r-cup", "CG10998"]],

        ["FBgn0024227", ["aurora b"]],
        ["FBgn0032850", ["CG10723/Kua"]],
        ["FBgn0029870", ["Mfn/Marf"]],
        ["FBgn0002862", ["mst87f"]],
        
        // TODO check this one-to-many mapping is valid       
        ["FBgn0003460", ["so-c", "so-n"]],
        
        ["FBgn0052394", ["CG32394N"]],
        ["FBgn0024956", ["mat1"]],
        ["FBgn0011260", ["CG4700-sema-2a"]],
        ["FBgn0051992", ["CG31992-gw"]],
        ["FBgn0000416", ["sapr"]],
        ["FBgn0028689", ["rpn6"]],
        
        // added assumed typo variant hale
        ["FBgn0036924", ["CG7570/hale", "hale"]],

        ["FBgn0037471", ["alh"]],
        ["FBgn0014037", ["su(tpl)"]],
        ["FBgn0031715", ["CG14016/tomb"]],
        ["FBgn0015277", ["Pi3k59F"]],
        ["FBgn0035231", ["Cct-2"]],

        // added assumed typo variant schuy
        ["FBgn0036925", ["CG17736/schuy", "schuy"]],

        // TODO check this one to many mapping is valid
        ["FBgn0038089", ["d-cup", "CG14387"]],
        
        // ["prosalpha1", "FBgn0026781 AND FBgn0050382"], // N.B. Helen says there is a gene duplication event, so genes are identical

        // added Prosalpha6 because assume same primer 
        ["FBgn0026781", ["prosalpha1", "Prosalpha6"]],
        ["FBgn0050382", ["prosalpha1", "Prosalpha6"]],  // TODO this fails, fixme
        
        ["FBgn0013997", ["Nrx4"]],
        ["FBgn0033929", ["tfb1"]],
        ["FBgn0003423", ["SlgA"]],
        
        // TODO check this one to many mapping is valid
        ["FBgn0030840", ["p-cup", "CG12993"]],

        ["FBgn0045800", ["CR32886-Uhg1"]],
        ["FBgn0016974", ["swapsi"]],
        ["FBgn0035106", ["Rno"]],
        ["FBgn0000964", ["CG10034/tj"]],
        ["FBgn0033313", ["cirl"]],
        ["FBgn0001941", ["des/ifc"]],
        ["FBgn0017556", ["Pros28.1b"]] 
        
    ];
    
    var assertB2TMapping = function(b, ets) {
        log("assert flybase name "+b+" maps to flyted names "+ets.join(", "), "test");
        
        var b2t = flyui.flyted.GeneNameMappings.flybaseToFlyted;
        var ats = b2t[b];

        assert.isNotUndefined(ats, "no mappings found for "+b);
        assert.isTrue(flyui.util.arrayMembersAreEqual(ets, ats), "expected: "+ets.join(", ")+", actual: "+ats.join(", "));        
        
    };
    
    for (var i=0; i<expectedB2TMappings.length; i++) {
        var mapping = expectedB2TMappings[i];
        var b = mapping[0];
        var ts = mapping[1];
        assertB2TMapping(b,ts);
    }
    
};


flyui.flyted.GeneNameMappings.Tests.testMappingsAreSymmetrical = function() {
    log("Test \"==== flyui.flyted.GeneNameMappings Tests :: testMappingsAreSymmetrical ====\" started.");

    var t2b = flyui.flyted.GeneNameMappings.flytedToFlybase;
    var b2t = flyui.flyted.GeneNameMappings.flybaseToFlyted;
    
    for (var t in t2b) {
    	var bs = t2b[t];
    	for (var i=0; i<bs.length; i++) {
    		var b = bs[i];
    		var rts = b2t[b];
    		assert.isNotUndefined(rts, "expected mappings for flybase name "+b);
    		assert.isTrue(flyui.util.isArrayMember(rts, t), "mapping not found for flybase name "+b+" to flyted name "+t);
    	}
    }
    
    for (var b in b2t) {
    	var ts = b2t[b];
    	for (var i=0; i<ts.length; i++) {
    		var t = ts[i];
    		var rbs = t2b[t];
            assert.isNotUndefined(rbs, "expected mappings for flyted name "+t);
            assert.isTrue(flyui.util.isArrayMember(rbs, b), "mapping not found for flyted name "+t+" to flybase name "+b);
    	}
    }
	
};


/**
 * TODO
 */
flyui.flyted.GeneNameMappings.TestCase = function (){
	var testCase = new YAHOO.tool.TestCase({
		
		name: "=== flyui.flyted.GeneNameMappings Tests ===",		
		testModuleContents : flyui.flyted.GeneNameMappings.Tests.testModuleContents,
		testMissingT2BMappingsAreNotMissing: flyui.flyted.GeneNameMappings.Tests.testMissingT2BMappingsAreNotMissing,
		testAmbiguousT2BMappingsAreFixed: flyui.flyted.GeneNameMappings.Tests.testAmbiguousT2BMappingsAreFixed,
		testB2TMappings: flyui.flyted.GeneNameMappings.Tests.testB2TMappings,
		testReverseOfNewT2BMappings: flyui.flyted.GeneNameMappings.Tests.testReverseOfNewT2BMappings,
		testMappingsAreSymmetrical: flyui.flyted.GeneNameMappings.Tests.testMappingsAreSymmetrical

	});
	
	return testCase;
}


// ************************************************************
// TEST SUITE AND RUNNER
// ************************************************************


/** 
 * Construct a YUI test suite for the flyui.flyted.GeneNameMappings module.
 * @param {String} endpointURL URL of service
 * @return a YUI test suite
 * @type YAHOO.tool.TestSuite
 */
flyui.flyted.GeneNameMappings.TestSuite = function() {
	var suite = new YAHOO.tool.TestSuite("== flyui.flyted.GeneNameMappings Test Suite ==");
	suite.add(flyui.flyted.GeneNameMappings.TestCase());
	return suite;
}


/** 
 * Run the flyui.flyted.GeneNameMappings test suite.
 * @param {String} endpointURL URL of service
 */
flyui.flyted.GeneNameMappings.runTests = function() {
	YAHOO.log("flyui.flyted.GeneNameMappings :: running tests", "test");
	YAHOO.tool.TestRunner.add(flyui.flyted.GeneNameMappings.TestSuite());
	YAHOO.tool.TestRunner.run();
}
